home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
nt
/
source.exe
/
POSIX
/
ELVIS
/
VIREC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-26
|
5KB
|
246 lines
/* virec.c */
/* Author:
* Steve Kirkendall
* 14407 SW Teal Blvd. #C
* Beaverton, OR 97005
* kirkenda@cs.pdx.edu
*/
/* This file contains the file recovery program */
#include "config.h"
#include <stdio.h>
#include <ctype.h>
#include "vi.h"
#if TOS
# include <stat.h>
#else
# if OSK
# include "osk.h"
# else
# include <sys/stat.h>
# endif
#endif
extern char *getenv();
struct stat stbuf;
BLK hdr;
BLK text;
/* the name of the directory where tmp files are stored. */
char o_directory[30] = TMPDIR;
char *progname;
main(argc, argv)
int argc;
char **argv;
{
char *tmp;
void recover();
#if MSDOS || TOS
char **wildexpand();
argv = wildexpand(&argc, argv);
#endif
progname = argv[0];
/* set the o_directory variable */
if ((tmp = getenv("TMP")) /* yes, ASSIGNMENT! */
|| (tmp = getenv("TEMP"))) /* yes, ASSIGNMENT! */
{
strcpy(o_directory, tmp);
}
if (argc >= 3 && !strcmp(argv[1], "-d"))
{
strcpy(o_directory, argv[2]);
argc -= 2;
argv += 2;
}
/* process the arguments */
if (argc < 2)
{
/* maybe stdin comes from a file? */
if (isatty(0))
{
fprintf(stderr, "usage: %s [-d tmpdir] lostfile...\n", progname);
}
else if (read(0, &hdr, (unsigned)BLKSIZE) != BLKSIZE)
{
fprintf(stderr, "couldn't get header\n");
}
else
{
copytext(0, stdout);
}
}
else
{
while (--argc > 0)
{
recover(*++argv);
}
}
exit(0);
}
/* This function recovers a single file */
void recover(filename)
char *filename;
{
char tmpname[100];
int tmpfd;
FILE *fp;
long mtime;
int i, j;
int sum; /* used for calculating a checksum for this */
char *scan;
/* get the file's status info */
if (stat(filename, &stbuf) < 0)
{
/* if serious error, give up on this file */
if (errno != ENOENT)
{
perror(filename);
return;
}
/* else fake it for a new file */
stat(".", &stbuf);
#if OSK
stbuf.st_mode = S_IREAD;
#else
stbuf.st_mode = S_IFREG;
#endif
stbuf.st_mtime = 0L;
}
/* generate a checksum from the file's name */
for (sum = 0, scan = filename + strlen(filename);
--scan >= filename && (isascii(*scan) && isalnum(*scan) || *scan == '.');
sum = sum + *scan)
{
}
sum &= 0xf;
/* find the tmp file */
#if MSDOS || TOS
/* MS-Dos doesn't allow multiple slashes, but supports drives
* with current directories.
* This relies on TMPNAME beginning with "%s\\"!!!!
*/
strcpy(tmpname, o_directory);
if ((i = strlen(tmpname)) && !strchr(":/\\", tmpname[i-1]))
tmpname[i++]=SLASH;
sprintf(tmpname+i, TMPNAME+3, sum, stbuf.st_ino, stbuf.st_dev);
#else
sprintf(tmpname, TMPNAME, o_directory, sum, stbuf.st_ino, stbuf.st_dev);
#endif
tmpfd = open(tmpname, O_RDONLY | O_BINARY);
if (tmpfd < 0)
{
perror(tmpname);
return;
}
/* make sure the file hasn't been modified more recently */
mtime = stbuf.st_mtime;
fstat(tmpfd, &stbuf);
if (stbuf.st_mtime < mtime)
{
printf("\"%s\" has been modified more recently than its recoverable version\n", filename);
puts("Do you still want to recover it?\n");
puts("\ty - Yes, discard the current version and recover it.\n");
puts("\tn - No, discard the recoverable version and keep the current version\n");
puts("\tq - Quit without doing anything for this file.\n");
puts("Enter y, n, or q --> ");
fflush(stdout);
for (;;)
{
switch (getchar())
{
case 'y':
case 'Y':
goto BreakBreak;
case 'n':
case 'N':
close(tmpfd);
unlink(tmpname);
return;
case 'q':
case 'Q':
close(tmpfd);
return;
}
}
BreakBreak:;
}
/* make sure this tmp file is intact */
if (read(tmpfd, &hdr, (unsigned)BLKSIZE) != BLKSIZE)
{
fprintf(stderr, "%s: bad header in tmp file\n", filename);
close(tmpfd);
unlink(tmpname);
return;
}
for (i = j = 1; i < MAXBLKS && hdr.n[i]; i++)
{
if (hdr.n[i] > j)
{
j = hdr.n[i];
}
}
lseek(tmpfd, (long)j * (long)BLKSIZE, 0);
if (read(tmpfd, &text, (unsigned)BLKSIZE) != BLKSIZE)
{
fprintf(stderr, "%s: bad data block in tmp file\n", filename);
close(tmpfd);
unlink(tmpname);
return;
}
/* open the normal text file for writing */
fp = fopen(filename, "w");
if (!fp)
{
perror(filename);
close(tmpfd);
return;
}
/* copy the text */
copytext(tmpfd, fp);
/* cleanup */
close(tmpfd);
fclose(fp);
unlink(tmpname);
}
/* This function moves text from the tmp file to the normal file */
copytext(tmpfd, fp)
int tmpfd; /* fd of the tmp file */
FILE *fp; /* the stream to write it to */
{
int i;
/* write the data blocks to the normal text file */
for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
{
lseek(tmpfd, (long)hdr.n[i] * (long)BLKSIZE, 0);
read(tmpfd, &text, (unsigned)BLKSIZE);
fputs(text.c, fp);
}
}
#if MSDOS || TOS
#define WILDCARD_NO_MAIN
#include "wildcard.c"
#endif